#region (c) 2014 THN Solutions LLC. - All rights reserved
/*
THN DATA ABSTRACTION LAYER version 1

Copyright (c) 2014, THN Solutions LLC. ( www.ThnSolutions.com )
Author: Nguyễn, M. Hải                 ( www.Minh-Hai.com     )
All rights reserved.

This library is dual-licensed.
  + For commercial software, please obtain a commercial license from THN Solutions LLC.

  + For free software, this library is licensed under GPL version 3. A summary of GPLv3 is
    listed below. You should also find a copy of GPLv3 as file License_GPLv3.txt included
	with the source-code files.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 3 as published by
    the Free Software Foundation  of the License.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#endregion

#region Using directives
using System;
using System.Collections;
#endregion

namespace Thn.Data.Query
{
    /// <summary>
    /// Base class for queries that supports conditions
    /// </summary>
    public abstract class ConditionalQuery: QueryBase
    {
        /// <summary>
        /// temporary holder for right-side condition
        /// </summary>
        protected SingleCondition conHolder = null;

        #region WhereClause
        private Condition mWhereClause = null;
        /// <summary>
        /// Gets/Sets Where information
        /// </summary>
        public Condition WhereClause
        {
            get { return mWhereClause; }
            set { mWhereClause = value; }
        }
        #endregion

        #region Condition

        #region Where
        /// <summary>
        /// Prepare to appends condition(s) to query
        /// </summary>
        public ConditionalQuery Where
        { get { return this; } }
        #endregion

        #region AND
        /// <summary>
        /// Prepare a new nested condition with operator AND        
        /// </summary>
        public ConditionalQuery And
        {
            get
            {
                if (mWhereClause == null) throw new Exception("Please specifies at least one condition before using operation AND");

                //create a new holder for right-side condition
                conHolder = new SingleCondition();
                //create a new nested condition
                NestedCondition nc = new NestedCondition(mWhereClause, conHolder);
                //assign the new nested condition to current condition (where clause)
                mWhereClause = nc;

                return this;
            }
        }
        #endregion

        #region OR
        /// <summary>
        /// Prepare a new nested condition with operator AND
        /// </summary>
        public ConditionalQuery Or
        {
            get
            {
                if (mWhereClause == null) throw new Exception("Please specifies at least one condition before using operation OR");

                //create a new holder for right-side condition
                conHolder = new SingleCondition();
                //create a new nested condition
                NestedCondition nc = new NestedCondition(mWhereClause, conHolder, CombinationType.Or);
                //assign the new nested condition to current condition (where clause)
                mWhereClause = nc;

                return this;
            }
        }
        #endregion

        #region Equal
        /// <summary>
        /// Append a condition where value of field must EQUAL the provided value
        /// </summary>
        /// <param name="fieldName">name of field to compare</param>
        /// <param name="value">value to compare against</param>
        public ConditionalQuery Equal(string fieldName, IComparable value)
        {
            //if currently no condition is available, create a new one
            if (conHolder == null)
            {
                conHolder = new SingleCondition();
                mWhereClause = conHolder;
            }

            //prepare condition
            conHolder.Field = fieldName;
            conHolder.Value = value;
            conHolder.Operation = ComparisionType.Equal;

            return this;
        }
        #endregion

        #region Not Equal
        /// <summary>
        /// Append a condition where value of field must NOT EQUAL the provided value
        /// </summary>
        /// <param name="fieldName">name of field to compare</param>
        /// <param name="value">value to compare against</param>
        public ConditionalQuery NotEqual(string fieldName, IComparable value)
        {
            //if currently no condition is available, create a new one
            if (conHolder == null)
            {
                conHolder = new SingleCondition();
                mWhereClause = conHolder;
            }

            //prepare condition
            conHolder.Field = fieldName;
            conHolder.Value = value;
            conHolder.Operation = ComparisionType.NotEqual;

            return this;
        }
        #endregion

        #region Greater
        /// <summary>
        /// Append a condition where value of field must GREATER the provided value
        /// </summary>
        /// <param name="fieldName">name of field to compare</param>
        /// <param name="value">value to compare against</param>
        public ConditionalQuery Greater(string fieldName, IComparable value)
        {
            //if currently no condition is available, create a new one
            if (conHolder == null)
            {
                conHolder = new SingleCondition();
                mWhereClause = conHolder;
            }

            //prepare condition
            conHolder.Field = fieldName;
            conHolder.Value = value;
            conHolder.Operation = ComparisionType.Greater;

            return this;
        }
        #endregion

        #region Greater Or Equal
        /// <summary>
        /// Append a condition where value of field must GREATER OR EQUAL the provided value
        /// </summary>
        /// <param name="fieldName">name of field to compare</param>
        /// <param name="value">value to compare against</param>
        public ConditionalQuery GreaterOrEqual(string fieldName, IComparable value)
        {
            //if currently no condition is available, create a new one
            if (conHolder == null)
            {
                conHolder = new SingleCondition();
                mWhereClause = conHolder;
            }

            //prepare condition
            conHolder.Field = fieldName;
            conHolder.Value = value;
            conHolder.Operation = ComparisionType.GreaterOrEqual;

            return this;
        }
        #endregion

        #region Less
        /// <summary>
        /// Append a condition where value of field must LESS than the provided value
        /// </summary>
        /// <param name="fieldName">name of field to compare</param>
        /// <param name="value">value to compare against</param>
        public ConditionalQuery Less(string fieldName, IComparable value)
        {
            //if currently no condition is available, create a new one
            if (conHolder == null)
            {
                conHolder = new SingleCondition();
                mWhereClause = conHolder;
            }

            //prepare condition
            conHolder.Field = fieldName;
            conHolder.Value = value;
            conHolder.Operation = ComparisionType.Less;

            return this;
        }
        #endregion

        #region Less Or Equal
        /// <summary>
        /// Append a condition where value of field must LESS OR EQUAL the provided value
        /// </summary>
        /// <param name="fieldName">name of field to compare</param>
        /// <param name="value">value to compare against</param>
        public ConditionalQuery LessOrEqual(string fieldName, IComparable value)
        {
            //if currently no condition is available, create a new one
            if (conHolder == null)
            {
                conHolder = new SingleCondition();
                mWhereClause = conHolder;
            }

            //prepare condition
            conHolder.Field = fieldName;
            conHolder.Value = value;
            conHolder.Operation = ComparisionType.LessOrEqual;

            return this;
        }
        #endregion

        #endregion

        #region Back
        /// <summary>
        /// Returns to the previous query level
        /// </summary>
        QueryBase Back
        { get { return mParentQuery; } }
        #endregion

        #region Constructors
        /// <summary>
        /// Default constructor
        /// </summary>
        public ConditionalQuery()
        { }
        #endregion
    }
}
